package com.shuqi.common.utils;

import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.apache.http.Header;
import org.apache.http.HeaderElement;
import org.apache.http.HttpEntity;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpRequestInterceptor;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.cookie.Cookie;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.protocol.HttpContext;

import com.shuqi.common.http.HttpResult;

/**
 * 
 */

/**
 * HTTP请求工具类
 * 
 * @author li.li
 * 
 * @date 2014-06-24
 */
public class HttpUtils {
    public static final String GZIP = "gzip";
    public static final String ENCODING = "utf-8";
    public static final int COMMON_TIMEOUT = 2 * 1000;// 连接超时
    public static final int COMMON_CONNECT_TIMEOUT = 30 * 1000;// 连接超时
    public static final int COMMON_SO_TIMEOUT = 30 * 1000;// 请求超时

    public static HttpResult get(DefaultHttpClient client, String url, Map<String, String> headers,
            Map<String, String> params) throws Throwable {

        return get(client, url, headers, params, HTTP.UTF_8);
    }

    public static HttpResult post(DefaultHttpClient client, String url,
            Map<String, String> headers, Map<String, String> params) throws Throwable {

        return post(client, url, headers, params, HTTP.UTF_8);
    }

    /**
     * ************************************************************************************** 以下私有方法
     * **************************************************************************************
     */

    private static HttpResult get(DefaultHttpClient client, String url,
            Map<String, String> headers, Map<String, String> params, String encoding)
            throws Throwable {

        url = url + (null == params ? "" : assemblyParameter(params));

        HttpGet get = new HttpGet(url);

        if (null != headers)
            get.setHeaders(assemblyHeader(headers));

        return execute(client, get);
    }

    private static HttpResult post(DefaultHttpClient client, String url,
            Map<String, String> headers, Map<String, String> params, String encoding)
            throws Throwable {

        HttpPost post = new HttpPost(url);

        if (null != headers)
            post.setHeaders(assemblyHeader(headers));

        if (params != null && !params.isEmpty()) {
            List<NameValuePair> list = new LinkedList<NameValuePair>();

            for (String temp : params.keySet()) {
                list.add(new BasicNameValuePair(temp, params.get(temp)));
            }

            post.setEntity(new UrlEncodedFormEntity(list, encoding));
        }

        return execute(client, post);
    }

    private static HttpResult execute(AbstractHttpClient client, HttpUriRequest request)
            throws Throwable {

        final HttpResponse response = client.execute(request);
        final HttpResult result = new HttpResult();

        if (response == null)
            return null;

        // 只有成功和重定向正常返回
        int code = response.getStatusLine().getStatusCode();

        if (HttpStatus.SC_OK == code || HttpStatus.SC_MOVED_PERMANENTLY == code
                || HttpStatus.SC_MOVED_TEMPORARILY == code) {// 只接受三种code

            result.setStatusCode(code);
            result.setHeaders(response.getAllHeaders());
            result.setCookie(assemblyCookie(client.getCookieStore().getCookies()));
            result.setCookieMap(assemblyCookieMap(client.getCookieStore().getCookies()));
            result.setHttpEntity(response.getEntity());
            result.setRequest(request);

            return result;

        } else {
            if (request != null)
                request.abort();
        }

        return null;

    }

    private static Header[] assemblyHeader(Map<String, String> headers) {
        final Header[] allHeader = new BasicHeader[headers.size()];
        int i = 0;
        for (String str : headers.keySet()) {
            allHeader[i] = new BasicHeader(str, headers.get(str));
            i++;
        }

        return allHeader;
    }

    private static String assemblyCookie(List<Cookie> cookies) {
        final StringBuffer sbu = new StringBuffer();

        for (Cookie cookie : cookies) {
            sbu.append(cookie.getName()).append("=").append(cookie.getValue()).append(";");
        }

        if (sbu.length() > 0)
            sbu.deleteCharAt(sbu.length() - 1);

        return sbu.toString();
    }

    private static Map<String, String> assemblyCookieMap(List<Cookie> cookies) {
        final Map<String, String> cookieMap = new HashMap<String, String>(cookies.size());

        for (Cookie cookie : cookies) {
            cookieMap.put(cookie.getName(), cookie.getValue());
        }

        return cookieMap;
    }

    private static String assemblyParameter(Map<String, String> parameters) {
        String para = "?";
        for (String str : parameters.keySet()) {
            para += str + "=" + parameters.get(str) + "&";
        }
        return para.substring(0, para.length() - 1);
    }

}
